{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# Python习题集\n",
    "\n",
    "与本习题集配套的教材和书籍：\n",
    "\n",
    "![](https://public-tuchuang.oss-cn-hangzhou.aliyuncs.com/%E8%BD%BB%E6%9D%BE%E5%85%A5%E9%97%A8_20200122130623.png)\n",
    "\n",
    "![](https://public-tuchuang.oss-cn-hangzhou.aliyuncs.com/my_book4_20200116132005.png)\n",
    "\n",
    "这两本书，各大电商平台均有售，请自购。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Python基础\n",
    "\n",
    "主要包括：\n",
    "\n",
    "- 内置对象类型：整数、浮点数、字符串、列表、字典、元组、集合等\n",
    "- 基本语法特性、关键词\n",
    "- 常用内置函数\n",
    "- 标准库\n",
    "- 第三方包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.14"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 绝对值或复数的模\n",
    "abs(-3.14)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.14\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "print(abs(-3.14))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.14"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "abs(-3.14)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 元素都为真\n",
    "# 接受一个迭代器，如果迭代器的所有元素都为真，那么返回True，否则返回False\n",
    "all([1,2,3,4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "all([1,2,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 元素至少一个为真\n",
    "# 接受一个迭代器，如果迭代器里至少有一个元素为真，那么返回True，否则返回False\n",
    "any([0,0,0,[]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "any([0,0,1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "print(all([1,[], 3])) #all()函数表示括号里的迭代器全部为真，则返回TRUE，否则返回FALSE\r\n",
    "print(any([0,0,1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "id = 001, name = xiaoming\n",
      "----------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'id = 001, name = xiaoming'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# ascii展示对象　　\n",
    "# 调用对象的__repr__() 方法，获得该方法的返回值，如下例子返回值为字符串。\n",
    "class Student:\n",
    "    def __init__(self,id,name):\n",
    "        self.id = id\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return 'id = '+self.id +', name = '+self.name\n",
    "        \n",
    "xiaoming = Student(id='001',name='xiaoming')\n",
    "print(xiaoming)\n",
    "\n",
    "print(\"-\"*10)\n",
    "\n",
    "ascii(xiaoming)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "id = 20214507018, name =chensongbai\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "class Student:\r\n",
    "    def __init__(self, id, name):\r\n",
    "        self.id = id\r\n",
    "        self.name = name\r\n",
    "    def connect(self):\r\n",
    "        return \"id = \" + self.id + \", name =\" + self.name\r\n",
    "\r\n",
    "csb = Student(\"20214507018\", \"chensongbai\")\r\n",
    "print(csb.connect()) \r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0xa'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "bin(10) #十进制转换成二进制\r\n",
    "hex(10) #十进制转换成十六进制"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0b1010'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将十进制转换为二进制\n",
    "bin(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0xf'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将十进制转换为十六进制\n",
    "hex(15)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'100'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "bool([1,2, ]) #布尔值转换\r\n",
    "str(100) #字符串转换\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试一个对象是True, 还是False.\n",
    "bool([0,0,0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bool([])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bool([1,0,1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'100'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将数值类型转换为字符串类型\n",
    "i = 100\n",
    "str(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'3.56'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 3.56\n",
    "str(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 判断对象是否可被调用，能被调用的对象就是一个callable 对象，比如函数 str, int 等都是可被调用的\n",
    "callable(str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "callable(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "id = 001, name = xiaoming"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xiaoming    # 在[7]中创建的实例对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "callable(xiaoming)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I can be called\n",
      "my name is xiaoming\n"
     ]
    }
   ],
   "source": [
    "# 如果想让xiaoming能被调用 xiaoming(), 需要重写Student类的__call__方法：\n",
    "class Student:\n",
    "    def __init__(self,id,name):\n",
    "        self.id = id\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return 'id = '+self.id +', name = '+self.name\n",
    "    def __call__(self):\n",
    "        print('I can be called')\n",
    "        print(f'my name is {self.name}')\n",
    "\n",
    "t = Student('001','xiaoming')\n",
    "t()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看十进制整数对应的ASCII字符\n",
    "chr(67)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "65"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看某个ASCII字符对应的十进制数\n",
    "ord('A')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 静态方法\n",
    "# classmethod 装饰器对应的函数不需要实例化，不需要 self 参数，但第一个参数需要是表示自身类的 cls 参数，可以来调用类的属性，类的方法，实例化对象等。\n",
    "class Student:\n",
    "    def __init__(self,id,name):\n",
    "        self.id = id\n",
    "        self.name = name\n",
    "    \n",
    "    def __repr__(self):\n",
    "        return 'id = '+self.id +', name = '+self.name\n",
    "         \n",
    "    @classmethod\n",
    "    def f(cls):\n",
    "        print(cls)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<code object <module> at 0x7fd6f0ae50c0, file \"<string>\", line 1>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 执行字符串表示的代码。将字符串编译成python能识别或可执行的代码，也可以将文字读成字符串再编译。\n",
    "s = \"print('helloworld')\"\n",
    "r = compile(s, '<string>', 'exec')\n",
    "r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "helloworld\n"
     ]
    }
   ],
   "source": [
    "exec(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1+2j)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建复数\n",
    "complex(1, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 动态删除属性\n",
    "delattr(xiaoming, 'id')    # xiaoming, [7]中创建的对象\n",
    "hasattr(xiaoming, 'id')   # 检查对象是否具有id属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建字典\n",
    "dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'a': 'csb', 'b': 'zhubei'}\n",
      "----------\n",
      "{'a': 'csb', 'b': 'zhubei'}\n",
      "----------\n",
      "{'a': 'csb', 'b': 'zhubei'}\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "print(dict(a = \"csb\", b = \"zhubei\"))\r\n",
    "print(\"-\"*10)\r\n",
    "print(dict(zip([\"a\",\"b\"],[\"csb\",\"zhubei\"])))\r\n",
    "print(\"-\"*10)\r\n",
    "print(dict([(\"a\",\"csb\"),(\"b\",\"zhubei\")]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'a': 1, 'b': 'laoqi'}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict(a=1, b='laoqi')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': '老齐', '公众号': '老齐教室'}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict(zip(['name', '公众号'], ['老齐', '老齐教室']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': '老齐', '公众号': '老齐教室'}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict([('name', '老齐'), ('公众号', '老齐教室')])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------------------------------------------------------------------------------------------------\n",
      "[(1, 'a'), (2, 'b'), (3, 'c')]\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "divmod(5,6) #同时返回商和余数的元组\r\n",
    "print(\"-\"*100)\r\n",
    "a = [\"a\",\"b\",\"c\"]\r\n",
    "print(list(enumerate(a,1))) #enumerate()枚举函数，返回[(,),(,)]枚举出来，(a, 1)a表示枚举的对象，1表示从1开始"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 2)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 取商和余数\n",
    "divmod(5, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 a\n",
      "2 b\n",
      "3 c\n"
     ]
    }
   ],
   "source": [
    "# 返回一个可以枚举的对象\n",
    "s = [\"a\",\"b\",\"c\"]\n",
    "for i ,v in enumerate(s,1):\n",
    "    print(i,v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将字符串str 当成有效的表达式来求值并返回计算结果取出字符串中内容\n",
    "s = \"1 + 3 +5\"\n",
    "eval(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "248"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看变量所占字节数\n",
    "import sys\n",
    "a = {'a':1,'b':2.0}\n",
    "sys.getsizeof(a)  # 结果为所占用的字节数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<filter object at 0x7f0550b0b9d0>\n",
      "----------\n",
      "[6, 7]\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "fill = filter(lambda x: x>5,[1,3,5,6,7])\r\n",
    "print(fill)\r\n",
    "print(\"-\"*10)\r\n",
    "print(list(fill))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[11, 45, 13]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在函数中设定过滤条件，迭代元素，保留返回值为True的元素\n",
    "fil = filter(lambda x: x>10,[1,11,2,45,7,6,13])\n",
    "list(fil)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.0"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转化为浮点数\n",
    "float(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i am tom,age18\n"
     ]
    }
   ],
   "source": [
    "# 格式化输出字符串，format(value, format_spec)实质上是调用了value的__format__(format_spec)方法\n",
    "print(\"i am {0},age{1}\".format(\"tom\",18))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "![](https://ai-studio-static-online.cdn.bcebos.com/d763ae4638d34fabb067ff6a53137ba448d218cbd0054e48bc150e3157d4bb77)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "frozenset({1, 2, 3})"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建一个不可修改的集合\n",
    "frozenset([1,1,3,2,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'xiaoming'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 获取对象的属性\n",
    "class Student:\n",
    "    def __init__(self,id,name):\n",
    "        self.id = id\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return 'id = '+self.id +', name = '+self.name\n",
    "\n",
    "xiaoming = Student(id='001',name='xiaoming')\n",
    "getattr(xiaoming,'name') # 获取xiaoming这个实例的name属性值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "----------\n",
      "20214507018\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "class Student:\r\n",
    "    def __init__(self, id, name):\r\n",
    "        self.id = id\r\n",
    "        self.name = name\r\n",
    "    def connect(self):\r\n",
    "        return \"id = \"+self.id+\", name = \"+self.name\r\n",
    "stu = Student(\"20214507018\", \"csb\")\r\n",
    "print(hasattr(stu, \"id\")) #在类Student中是否有id这个属性\r\n",
    "print(\"-\"*10)\r\n",
    "print(getattr(stu, \"id\")) #得到类Student中id这个属性值\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 判断是否有这个属性\n",
    "class Student:\n",
    "    def __init__(self,id,name):\n",
    "        self.id = id\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return 'id = '+self.id +', name = '+self.name\n",
    "\n",
    "xiaoming = Student(id='001',name='xiaoming')\n",
    "hasattr(xiaoming,'name')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hasattr(xiaoming,'address')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8785071096297"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回对象的哈希值，list, dict, set等可变对象都是不可哈希的(unhashable)\n",
    "hash(xiaoming)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-43-84d65be9aa35>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mhash\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "hash([1, 2, 3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "140561137540752"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回对象的内存地址\n",
    "id(xiaoming)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "csb loves who?i loves zhubei\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "a = input(\"csb loves who?\")\r\n",
    "if a == \"zhubei\":\r\n",
    "    print(\"i loves {}\".format(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input something:"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'jhlkj'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 捕获键盘输入\n",
    "input('input something:')    # 写完这行，就执行本单元，在此处在线平台中，会出现输入框，等待输入。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "15\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "float(\"3.4\")\r\n",
    "print(\"-\"*10)\r\n",
    "print(int(\"13\",12))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "invalid literal for int() with base 10: '3.14'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-50-b2318607336b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# int(x, base =10) , x可能为字符串或数值，将x 转换为一个普通整数。如果参数是字符串，那么它可能包含符号和小数点。\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'3.14'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: '3.14'"
     ]
    }
   ],
   "source": [
    "# int(x, base =10) , x可能为字符串或数值，将x 转换为一个普通整数。如果参数是字符串，那么它可能包含符号和小数点。\n",
    "int('3.14')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int('3')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "18"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int('12', 16)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 判断实例对象是否为某个类的实例，是返回True\n",
    "class Student:\n",
    "    def __init__(self,id,name):\n",
    "        self.id = id\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return 'id = '+self.id +', name = '+self.name\n",
    "\n",
    "xiaoming = Student(id='001',name='xiaoming')\n",
    "\n",
    "isinstance(xiaoming,Student)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 判断类的继承关系\n",
    "class Undergraduate(Student):\n",
    "    def studyClass(self):\n",
    "        pass\n",
    "    def attendActivity(self):\n",
    "        pass\n",
    "\n",
    "issubclass(Undergraduate,Student)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "issubclass(object,Student)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "issubclass(Student,object)    # object是所有类的基类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "issubclass(int, (int,float))    # 如果类是元组中某个元素，也会返回True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<list_iterator at 0x7fd6f09f3910>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用iter(obj, sentinel), 返回一个迭代器对象, sentinel可省略(一旦迭代到此元素，立即终止)\n",
    "iter_lst = iter([1, 3, 5])\n",
    "iter_lst"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__call__ is called,fowhich would return 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class TestIter(object):\n",
    "    def __init__(self):\n",
    "        self.l=[1,3,2,3,4,5]\n",
    "        self.i=iter(self.l)\n",
    "    \n",
    "    def __call__(self):  #定义了__call__方法的类的实例是可调用的\n",
    "        item = next(self.i)\n",
    "        print (\"__call__ is called,fowhich would return\",item)\n",
    "        return item\n",
    "    \n",
    "    def __iter__(self): #支持迭代协议(即定义有__iter__()函数)\n",
    "        print (\"__iter__ is called!!\")\n",
    "        return iter(self.l)\n",
    "\n",
    "t = TestIter()\n",
    "t() # 因为实现了__call__，所以t实例能被调用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__iter__ is called!!\n",
      "1\n",
      "3\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "for e in TestIter(): # 因为实现了__iter__方法，所以t能被迭代\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "object"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# object 是所有类的基类\n",
    "base_klass = object()\n",
    "type(base_klass)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'csb loves zhubei'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "a = \"csb loves zhubei\"\r\n",
    "f = open(\"python_learning.txt\", \"w\")\r\n",
    "f.write(a)\r\n",
    "f.close\r\n",
    "f = open(\"python_learning.txt\", \"r\")\r\n",
    "f.read()\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'测试文件写入测试文件写入'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 打开文件\n",
    "f = open('work/python.txt', mode='r')\n",
    "f.read()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "![](https://ai-studio-static-online.cdn.bcebos.com/ac77841e71574cd5856d9c57631b6269d7045897db2e45fd83af3e3cadcd2720)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 幂运算函数\n",
    "pow(2, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1024\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "print(pow(2,10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pow(2, 3, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 3, 5]\n",
      "lst: [1, 3, 5]\n",
      "lst:[1, 3, 5]\n",
      "lst: [1, 3, 5]\n"
     ]
    }
   ],
   "source": [
    "# print函数\n",
    "lst = [1,3,5]\n",
    "\n",
    "print(lst)\n",
    "\n",
    "print(f'lst: {lst}')\n",
    "\n",
    "print('lst:{}'.format(lst))\n",
    "\n",
    "print('lst:',lst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 返回 property 属性\n",
    "class C:\n",
    "    def __init__(self):\n",
    "        self._x = None\n",
    "\n",
    "    def getx(self):\n",
    "        return self._x\n",
    "\n",
    "    def setx(self, value):\n",
    "        self._x = value\n",
    "\n",
    "    def delx(self):\n",
    "        del self._x\n",
    "    # 使用property类创建 property 属性\n",
    "    x = property(getx, setx, delx, \"I'm the 'x' property.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 使用python装饰器，实现与上完全一样的效果代码：\n",
    "class C:\n",
    "    def __init__(self):\n",
    "        self._x = None\n",
    "\n",
    "    @property\n",
    "    def x(self):\n",
    "        return self._x\n",
    "\n",
    "    @x.setter\n",
    "    def x(self, value):\n",
    "        self._x = value\n",
    "\n",
    "    @x.deleter\n",
    "    def x(self):\n",
    "        del self._x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(0, 10)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# range(stop)\n",
    "# range(start, stop[,step])\n",
    "# 生成一个不可变序列\n",
    "\n",
    "range(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "range(0, 10, 2)\n",
      "----------\n",
      "[0, 2, 4, 6, 8]\n",
      "----------\n",
      "[1, 6, 4, 3]\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "print(range(0,10,2))\r\n",
    "print(\"-\"*10)\r\n",
    "print(list(range(0, 10, 2)))\r\n",
    "print(\"-\"*10)\r\n",
    "print(list(reversed([3, 4, 6, 1])))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(0, 100, 3)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "range(0, 100, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n",
      "6\n",
      "2\n",
      "5\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "# 反序\n",
    "rev = reversed([1, 5, 2, 6, 7])\n",
    "for i in rev:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.142"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 四舍五入，ndigits代表小数点后保留几位\n",
    "round(3.1415926, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1, 2, 4, 6, 9}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转为集合类型，简单的去重方法\n",
    "a = [1, 4, 2, 4, 6, 6, 9]\n",
    "set(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.14\n",
      "----------\n",
      "{1, 2, 3, 4, 6}\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "a = 3.1415926\r\n",
    "b = [1, 2, 3, 4, 6, 2, 2]\r\n",
    "print(round(a, 2))\r\n",
    "print(\"-\"*10)\r\n",
    "print(set(b)) #使用set()集合函数去重"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 6]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# slice函数， 转为切片对象. 返回一个表示由 range(start, stop, step) 所指定索引集的 slice对象，它让代码可读性、可维护性变好\n",
    "a = [1, 4, 2, 4, 6, 6, 9]\n",
    "sli = slice(0, 5, 2)    # 切片的范围和步长\n",
    "a[sli]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 5, 9]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# sorted函数\n",
    "lst = [3, 2, 5, 1, 9]\n",
    "sorted(lst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'name': 'xiaoming', 'age': 18, 'gender': 'male'},\n",
       " {'name': 'xiaohong', 'age': 20, 'gender': 'female'}]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [{'name':'xiaoming','age':18,'gender':'male'},{'name':'xiaohong','age':20,'gender':'female'}]\n",
    "sorted(a,key=lambda x: x['age'],reverse=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求和\n",
    "lst = [1, 3, 5]\n",
    "sum(lst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "19"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(lst, 10)    # 以10为求和的开始，即将lst中各数的和加10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 3, 5)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转化为元组\n",
    "tuple([1, 3, 5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "__main__.Student"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看对象类型\n",
    "class Student:\n",
    "    def __init__(self,id,name):\n",
    "        self.id = id\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return 'id = '+self.id +', name = '+self.name\n",
    "    \n",
    "xiaoming = Student(id='001',name='xiaoming')\n",
    "type(xiaoming)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('a', 1), ('b', 2), ('c', 3)]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# zip函数的应用\n",
    "x = ['a', 'b', 'c']\n",
    "y = [1, 2, 3, 4]\n",
    "list(zip(x, y))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['a1', 'b2', 'c3']"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[i+str(j) for i, j in zip(x, y)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 关键词nonlocal常用于函数嵌套中，声明变量i为非局部变量； 如果不声明，i+=1表明i为函数wrapper内的局部变量，因为在i+=1引用(reference)时,i未被声明，所以会报unreferenced variable的错误。\n",
    "def excepter(f):\n",
    "    i = 0\n",
    "    t1 = time.time()\n",
    "    def wrapper(): \n",
    "        try:\n",
    "            f()\n",
    "        except Exception as e:\n",
    "            nonlocal i\n",
    "            i += 1\n",
    "            print(f'{e.args[0]}: {i}')\n",
    "            t2 = time.time()\n",
    "            if i == n:\n",
    "                print(f'spending time:{round(t2-t1,2)}')\n",
    "    return wrapper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "# 关键词：global，声明全局变量\n",
    "i = 5\n",
    "def f():\n",
    "    print(i)\n",
    "\n",
    "def g():\n",
    "    print(i)\n",
    "    pass\n",
    "\n",
    "f()\n",
    "g()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "UnboundLocalError",
     "evalue": "local variable 'i' referenced before assignment",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mUnboundLocalError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-85-5728641c02ba>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      4\u001b[0m    \u001b[0mi\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mh\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m   \u001b[0;31m# 报错\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-85-5728641c02ba>\u001b[0m in \u001b[0;36mh\u001b[0;34m()\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;31m# 但是，如果我想要有个函数对i递增，这样：\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mh\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m    \u001b[0mi\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[0mh\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m   \u001b[0;31m# 报错\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'i' referenced before assignment"
     ]
    }
   ],
   "source": [
    " # f和g两个函数都能共享变量i，程序没有报错.\n",
    "# 但是，如果我想要有个函数对i递增，这样：\n",
    "def h():\n",
    "    i += 1\n",
    "\n",
    "h()   # 报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "# global就是为解决此问题而被提出，在函数h内，显示地告诉编译器i为全局变量，然后编译器会在函数外面寻找i的定义，执行完i+=1后，i还为全局变量，值加1：\n",
    "i = 0\n",
    "def h():\n",
    "    global i\n",
    "    i += 1\n",
    "\n",
    "h()\n",
    "print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# 链式比较\n",
    "i = 3\n",
    "print(1 < i < 3)  # False，相当于(1<i) and (i<3)\n",
    "print(1 < i <= 3)  # True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 不用else和if实现计算器\n",
    "from operator import *\n",
    "\n",
    "\n",
    "def calculator(a, b, k):\n",
    "    return {\n",
    "        '+': add,\n",
    "        '-': sub,\n",
    "        '*': mul,\n",
    "        '/': truediv,\n",
    "        '**': pow\n",
    "    }[k](a, b)\n",
    "\n",
    "calculator(1, 2, '+')  # 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "81"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calculator(3, 4, '**')  # 81"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 链式操作\n",
    "from operator import (add, sub)\n",
    "\n",
    "def add_or_sub(a, b, oper):\n",
    "    return (add if oper == '+' else sub)(a, b)\n",
    "\n",
    "add_or_sub(1, 2, '-') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "# 交换对象\n",
    "a = 1\n",
    "b = 3\n",
    "\n",
    "a, b = b, a\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9.1"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算平均值\n",
    "def score_mean(lst):\n",
    "    lst.sort()\n",
    "    lst2=lst[1:(len(lst)-1)]\n",
    "    return round((sum(lst2)/len(lst2)),1)\n",
    "\n",
    "lst=[9.1, 9.0,8.1, 9.7, 19,8.2, 8.6,9.8]\n",
    "score_mean(lst) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1*1\t\n",
      "2*1\t2*2\t\n",
      "3*1\t3*2\t3*3\t\n",
      "4*1\t4*2\t4*3\t4*4\t\n",
      "5*1\t5*2\t5*3\t5*4\t5*5\t\n",
      "6*1\t6*2\t6*3\t6*4\t6*5\t6*6\t\n",
      "7*1\t7*2\t7*3\t7*4\t7*5\t7*6\t7*7\t\n",
      "8*1\t8*2\t8*3\t8*4\t8*5\t8*6\t8*7\t8*8\t\n",
      "9*1\t9*2\t9*3\t9*4\t9*5\t9*6\t9*7\t9*8\t9*9\t\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "for i in range(1,10):\r\n",
    "    for j in range(1,i+1):\r\n",
    "        print(\"{}*{}\".format(i, j, i*j), end=\"\\t\")\r\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1*1=1\t\n",
      "1*2=2\t2*2=4\t\n",
      "1*3=3\t2*3=6\t3*3=9\t\n",
      "1*4=4\t2*4=8\t3*4=12\t4*4=16\t\n",
      "1*5=5\t2*5=10\t3*5=15\t4*5=20\t5*5=25\t\n",
      "1*6=6\t2*6=12\t3*6=18\t4*6=24\t5*6=30\t6*6=36\t\n",
      "1*7=7\t2*7=14\t3*7=21\t4*7=28\t5*7=35\t6*7=42\t7*7=49\t\n",
      "1*8=8\t2*8=16\t3*8=24\t4*8=32\t5*8=40\t6*8=48\t7*8=56\t8*8=64\t\n",
      "1*9=9\t2*9=18\t3*9=27\t4*9=36\t5*9=45\t6*9=54\t7*9=63\t8*9=72\t9*9=81\t\n"
     ]
    }
   ],
   "source": [
    "# 打印99乘法表\n",
    "# 一共有10 行，第i行的第j列等于：j*i，\n",
    "# 其中,\n",
    "# i取值范围：1<=i<=9\n",
    "# j取值范围：1<=j<=i\n",
    "for i in range(1,10):\n",
    "    for j in range(1,i+1):\n",
    "        print('%d*%d=%d'%(j,i,j*i),end=\"\\t\")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5]\n",
      "[6, 7, 1, 2, 3, 4, 5]\n",
      "[1, 2, 3, 4, 5, 6]\n"
     ]
    }
   ],
   "source": [
    "# 将列表[[[1,2,3],[4,5]]]，展开为一维。\n",
    "\n",
    "from collections.abc import *\n",
    "\n",
    "def flatten(lst, out_lst=None):\n",
    "    if out_lst is None:\n",
    "        out_lst = []\n",
    "    for i in lst:\n",
    "        if isinstance(i, Iterable): # 判断i是否可迭代\n",
    "            flatten(i, out_lst)  # 尾数递归\n",
    "        else:\n",
    "            out_lst.append(i)    # 产生结果\n",
    "    return out_lst\n",
    "    \n",
    "print(flatten([[1,2,3],[4,5]]))\n",
    "print(flatten([[1,2,3],[4,5]], [6,7]))\n",
    "print(flatten([[[1,2,3],[4,5,6]]]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([list([1, 2, 3]), list([4, 5])], dtype=object)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# numpy里的flatten与上面的函数实现有些微妙的不同\n",
    "import numpy as np\n",
    "b = np.array([[1,2,3],[4,5]])\n",
    "b.flatten()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1, 3], [5, 7], [9]]\n",
      "[[1, 3, 5, 7, 9]]\n",
      "[[1, 3, 5, 7, 9]]\n"
     ]
    }
   ],
   "source": [
    "# 等分列表\n",
    "\n",
    "from math import ceil\n",
    "\n",
    "def divide(lst, size):\n",
    "    if size <= 0:\n",
    "        return [lst]\n",
    "    return [lst[i * size:(i+1)*size] for i in range(0, ceil(len(lst) / size))]\n",
    "\n",
    "\n",
    "r = divide([1, 3, 5, 7, 9], 2)\n",
    "print(r)\n",
    "\n",
    "r = divide([1, 3, 5, 7, 9], 0)\n",
    "print(r) \n",
    "\n",
    "r = divide([1, 3, 5, 7, 9], -3)\n",
    "print(r) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['ok', [1, 2]]\n"
     ]
    }
   ],
   "source": [
    "# 列表压缩\n",
    "def filter_false(lst):\n",
    "    return list(filter(bool, lst))\n",
    "\n",
    "\n",
    "r = filter_false([None, 0, False, '', [], 'ok', [1, 2]])\n",
    "print(r)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "更长的列表是[4, 5, 6, 7]\n",
      "更长的列表是[4, 5, 6, 7]\n"
     ]
    }
   ],
   "source": [
    "# 选出长度值大的列表\n",
    "def max_length(*lst):\n",
    "    return max(*lst, key=lambda v: len(v))\n",
    "\n",
    "r = max_length([1, 2, 3], [4, 5, 6, 7], [8])\n",
    "print(f'更长的列表是{r}')  \n",
    "\n",
    "r = max_length([1, 2, 3], [4, 5, 6, 7], [8, 9])\n",
    "print(f'更长的列表是{r}') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 3, 3, 2, 1, 1, 2]中出现次数最多的元素为:1\n"
     ]
    }
   ],
   "source": [
    "# 计算众数\n",
    "def top1(lst):\n",
    "    return max(lst, default='列表为空', key=lambda v: lst.count(v))\n",
    "\n",
    "lst = [1, 3, 3, 2, 1, 1, 2]\n",
    "r = top1(lst)\n",
    "print(f'{lst}中出现次数最多的元素为:{r}')  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8\n"
     ]
    }
   ],
   "source": [
    "# 找出多个列表中最大值\n",
    "def max_lists(*lst):\n",
    "    return max(max(*lst, key=lambda v: max(v)))\n",
    "\n",
    "\n",
    "r = max_lists([1, 2, 3], [6, 7, 8], [4, 5])\n",
    "print(r) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 检查列表中是否有重复元素\n",
    "def has_duplicates(lst):\n",
    "    return len(lst) == len(set(lst))\n",
    "\n",
    "\n",
    "x = [1, 1, 2, 2, 3, 2, 3, 4, 5, 6]\n",
    "has_duplicates(x)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = [1, 2, 3, 4, 5]\n",
    "has_duplicates(y)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 1, 4, 3, -2, 1]\n"
     ]
    }
   ],
   "source": [
    "# 列表反转\n",
    "def reverse(lst):\n",
    "    return lst[::-1]\n",
    "\n",
    "r = reverse([1, -2, 3, 4, 1, 2])\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1.0, 1.7, 2.4, 3.1, 3.8, 4.5, 5.2, 5.9, 6.6, 7.3, 8.0]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 浮点数的等差数列\n",
    "\n",
    "def rang(start, stop, n):\n",
    "    start,stop,n = float('%.2f' % start), float('%.2f' % stop),int('%.d' % n)\n",
    "    step = (stop-start)/n\n",
    "    lst = [start]\n",
    "    while n > 0:\n",
    "        start,n = start+step,n-1\n",
    "        lst.append(round((start), 2))\n",
    "    return lst\n",
    "\n",
    "rang(1, 8, 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[25, 31, 34], [89]]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 按条件分组\n",
    "\n",
    "def bif_by(lst, f):\n",
    "    return [ [x for x in lst if f(x)],[x for x in lst if not f(x)]]\n",
    "\n",
    "records = [25,89,31,34] \n",
    "bif_by(records, lambda x: x<80) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4, 9, 16, 25, 16, 13]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# map实现向量运算\n",
    "lst1=[1,2,3,4,5,6]\n",
    "lst2=[3,4,5,6,3,2]\n",
    "list(map(lambda x,y:x*y+1, lst1, lst2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('b', 5), ('d', 5)]\n"
     ]
    }
   ],
   "source": [
    "# 选出字典中值最大的键值对\n",
    "def max_pairs(dic):\n",
    "    if len(dic) == 0:\n",
    "        return dic\n",
    "    max_val = max(map(lambda v: v[1], dic.items()))\n",
    "    return [item for item in dic.items() if item[1] == max_val]\n",
    "\n",
    "\n",
    "r = max_pairs({'a': -10, 'b': 5, 'c': 3, 'd': 5})\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'a': 1, 'b': 2, 'c': 3}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 合并两个字典\n",
    "\n",
    "def merge_dict(dic1, dic2):\n",
    "    return {**dic1, **dic2}  # python3.5后支持的一行代码实现合并字典\n",
    "\n",
    "merge_dict({'a': 1, 'b': 2}, {'c': 3}) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ChainMap({'x': 1, 'y': 2}, {'y': 3, 'z': 4})\n"
     ]
    }
   ],
   "source": [
    "# 合并字典的另外方法\n",
    "from collections import ChainMap\n",
    "\n",
    "dic1 = {'x': 1, 'y': 2 }\n",
    "dic2 = {'y': 3, 'z': 4 }\n",
    "merged2 = ChainMap(dic1,dic2)\n",
    "print(merged2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['a', 'd', 'c']"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回字典d前n个最大值对应的键\n",
    "\n",
    "from heapq import nlargest\n",
    "\n",
    "def topn_dict(d, n):\n",
    "    return nlargest(n, d, key=lambda k: d[k])\n",
    "\n",
    "topn_dict({'a': 10, 'b': 8, 'c': 9, 'd': 10}, 3) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 检查两个字符串是否 相同字母异序词，简称：互为变位词\n",
    "\n",
    "from collections import Counter\n",
    "\n",
    "def anagram(str1, str2):\n",
    "    return Counter(str1) == Counter(str2)\n",
    "\n",
    "anagram('eleven+two', 'twelve+one')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "anagram('eleven', 'twelve')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'nohtyp'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 反转字符串\n",
    "\n",
    "st=\"python\"\n",
    "#方法1\n",
    "''.join(reversed(st))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'nohtyp'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#方法2\n",
    "st[::-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['1',\n",
       " '2',\n",
       " 'java',\n",
       " '4',\n",
       " 'python',\n",
       " 'java',\n",
       " '7',\n",
       " '8',\n",
       " 'java',\n",
       " 'python',\n",
       " '11',\n",
       " 'java',\n",
       " '13',\n",
       " '14']"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 字符串切片操作，查找替换3或5的倍数\n",
    "[str(\"java\"[i%3*4:]+\"python\"[i%5*6:] or i) for i in range(1,15)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1,2,java,4,python,java,7,8,java,python,11,java,13,14'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# join连接字符串\n",
    "lst = [str(\"java\"[i%3*4:]+\"python\"[i%5*6:] or i) for i in range(1,15)]\n",
    "','.join(lst) #用逗号连接字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(7, 13)\n"
     ]
    }
   ],
   "source": [
    "# 正则模块的使用方法\n",
    "\n",
    "import re\n",
    "\n",
    "s = 'i love python very much'\n",
    "pat = 'python' \n",
    "r = re.search(pat,s)\n",
    "print(r.span())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<re.Match object; span=(1, 3), match='老齐'>\n"
     ]
    }
   ],
   "source": [
    "# 查找指定字符的索引\n",
    "\n",
    "s = \"跟老齐学Python：轻松入门\"\n",
    "pat = '老齐'\n",
    "r = re.finditer(pat, s)\n",
    "for i in r:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['1', '52', '9']\n"
     ]
    }
   ],
   "source": [
    "s = \"这是第1本书，价格是52.9元\"\n",
    "pat = r'\\d+'    # +表示匹配数字(\\d表示数字的通用字符)1次或多次\n",
    "r = re.findall(pat, s)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['52.9']\n"
     ]
    }
   ],
   "source": [
    "pat = r'\\d+\\.?\\d+' # ?表示匹配小数点(\\.)0次或1次\n",
    "r = re.findall(pat,s)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n"
     ]
    }
   ],
   "source": [
    "# 查找以字符s, p开始的字符串\n",
    "s = 'life is short you need python'\n",
    "pat = r'^[sp]' \n",
    "r = re.findall(pat,s)\n",
    "print(r)     # 字符串s是以l开头，不在pat所示范围"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['life is short you need python']\n"
     ]
    }
   ],
   "source": [
    "r = re.findall('^[lp].*', s)   # # 匹配以l, p开始的字符串，后面是多个任意字符\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['T', 't']"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 忽略大小写\n",
    "s = 'That'\n",
    "pat = r't' \n",
    "r = re.findall(pat,s,re.I)\n",
    "r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "str contains special characters:#\n"
     ]
    }
   ],
   "source": [
    "# compile的作用\n",
    "import re\n",
    "pat = re.compile('\\W+')    # \\W 匹配不是数字和字母的字符\n",
    "has_special_chars = pat.search('ed#2@edc') \n",
    "if has_special_chars:\n",
    "    print(f'str contains special characters:{has_special_chars.group(0)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "possibly it is an email\n"
     ]
    }
   ],
   "source": [
    "# 再次使用pat正则编译对象 做匹配\n",
    "again_pattern = pat.findall('guozhennianhua@163.com')\n",
    "if '@' in again_pattern:\n",
    "    print('possibly it is an email')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']\n"
     ]
    }
   ],
   "source": [
    "# 使用()捕获单词，不想带空格\n",
    "s = 'This module provides regular expression matching operations similar to those found in Perl'\n",
    "pat = r'\\s([a-zA-Z]+)'  \n",
    "r = re.findall(pat,s)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['This', 'module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']\n"
     ]
    }
   ],
   "source": [
    "# 以上提取单词中未包括第一个单词，使用?表示前面字符出现0次或1次，但是此字符还有表示贪心或非贪心匹配含义，使用时要谨慎\n",
    "s = 'This module provides regular expression matching operations similar to those found in Perl'\n",
    "pat = r'\\s?([a-zA-Z]+)'  \n",
    "r = re.findall(pat,s)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['This', 'module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']\n"
     ]
    }
   ],
   "source": [
    "# split分割单词，这个方法更简单\n",
    "s = 'This module provides regular expression matching operations similar to those found in Perl'\n",
    "pat = r'\\s+'  \n",
    "r = re.split(pat,s)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['This', 'module', 'provides', 'regular']\n"
     ]
    }
   ],
   "source": [
    "s = 'This,,,   module ; \\t   provides|| regular ; '\n",
    "words = re.split('[,\\s;|]+',s)           #这样分隔出来，最后会有一个空字符串\n",
    "words = [i for i in words if len(i)>0]\n",
    "print(words)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<re.Match object; span=(1, 3), match='hi'>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 从字符串开始位置匹配\n",
    "\n",
    "import re\n",
    "\n",
    "mystr = 'This'\n",
    "pat = re.compile('hi')\n",
    "pat.match(mystr) # None\n",
    "pat.match(mystr,1) # 从位置1处开始匹配"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<re.Match object; span=(1, 3), match='hi'>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# search是从字符串的任意位置开始匹配\n",
    "mystr = 'This'\n",
    "pat = re.compile('hi')\n",
    "pat.search(mystr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello 666, hello 666\n"
     ]
    }
   ],
   "source": [
    "# sub函数实现对匹配子串的替换\n",
    "content=\"hello 12345, hello 456321\"    \n",
    "pat=re.compile(r'\\d+') #要替换的部分\n",
    "m=pat.sub(\"666\",content)\n",
    "print(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['graph</div>bb<div>math']\n"
     ]
    }
   ],
   "source": [
    "# (.*)表示捕获任意多个字符，尽可能多的匹配字符\n",
    "content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'\n",
    "pat=re.compile(r\"<div>(.*)</div>\")  #贪婪模式\n",
    "m=pat.findall(content)\n",
    "print(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['graph', 'math']\n"
     ]
    }
   ],
   "source": [
    "# 非贪心捕获。仅添加一个问号(?)，得到结果完全不同，这是非贪心匹配，通过这个例子体会贪心和非贪心的匹配的不同\n",
    "content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'\n",
    "pat=re.compile(r\"<div>(.*?)</div>\")\n",
    "m=pat.findall(content)\n",
    "print(m) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 常用元字符总结\n",
    "\n",
    "- . 匹配任意字符  \n",
    "- ^ 匹配字符串开始位置 \n",
    "- $ 匹配字符串中结束的位置 \n",
    "- * 前面的原子重复0次、1次、多次 \n",
    "- ? 前面的原子重复0次或者1次 \n",
    "- + 前面的原子重复1次或多次\n",
    "- {n} 前面的原子出现了 n 次\n",
    "- {n,} 前面的原子至少出现 n 次\n",
    "- {n,m} 前面的原子出现次数介于 n-m 之间\n",
    "- ( ) 分组,需要输出的部分\n",
    "\n",
    "## 常用通用字符总结\n",
    "\n",
    "- \\s  匹配空白字符 \n",
    "- \\w  匹配任意字母/数字/下划线 \n",
    "- \\W  和小写 w 相反，匹配任意字母/数字/下划线以外的字符\n",
    "- \\d  匹配十进制数字\n",
    "- \\D  匹配除了十进制数以外的值 \n",
    "- [0-9]  匹配一个0-9之间的数字\n",
    "- [a-z]  匹配小写英文字母\n",
    "- [A-Z]  匹配大写英文字母"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 're' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_133/1382626864.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;31m# 2)密码只包含英文字母和数字\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mpat\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mre\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompile\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mr'\\w{6,20}'\u001b[0m\u001b[0;34m)\u001b[0m    \u001b[0;31m# 这是错误的，因为\\w通配符匹配的是字母，数字和下划线，题目要求不能含有下划线\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      6\u001b[0m \u001b[0;31m# 使用最稳的方法：\\da-zA-Z满足`密码只包含英文字母和数字`\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0mpat\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mre\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompile\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mr'[\\da-zA-Z]{6,20}'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 're' is not defined"
     ]
    }
   ],
   "source": [
    "# 密码安全要求：\n",
    "# 1)要求密码为6到20位; \n",
    "# 2)密码只包含英文字母和数字\n",
    "\n",
    "pat = re.compile(r'\\w{6,20}')    # 这是错误的，因为\\w通配符匹配的是字母，数字和下划线，题目要求不能含有下划线\n",
    "# 使用最稳的方法：\\da-zA-Z满足`密码只包含英文字母和数字`\n",
    "pat = re.compile(r'[\\da-zA-Z]{6,20}')\n",
    "\n",
    "pat.fullmatch('qaz12') # 返回 None, 长度小于6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "pat.fullmatch('qaz12wsxedcrfvtgb67890942234343434') # None 长度大于22"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "pat.fullmatch('qaz_231') # None 含有下划线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<re.Match object; span=(0, 10), match='n0passw0Rd'>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pat.fullmatch('n0passw0Rd')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<re.Match object; span=(940, 964), match='<title>百度一下，你就知道</title>'>\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'<title>百度一下，你就知道</title>'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 简单爬虫，爬取百度首页标题，练习正则表达式\n",
    "\n",
    "import re\n",
    "from urllib import request\n",
    "\n",
    "#爬虫爬取百度首页内容\n",
    "data=request.urlopen(\"http://www.baidu.com/\").read().decode()\n",
    "\n",
    "#分析网页,确定正则表达式\n",
    "pat=r'<title>(.*?)</title>'\n",
    "\n",
    "result=re.search(pat,data)\n",
    "print(result) \n",
    "result.group()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 数据库字段名批量转化为驼峰格式\n",
    "\n",
    "# 用到的正则串讲解\n",
    "# \\s 指匹配： [ \\t\\n\\r\\f\\v]\n",
    "# A|B：表示匹配A串或B串\n",
    "# re.sub(pattern, newchar, string): \n",
    "# substitue代替，用newchar字符替代与pattern匹配的字符所有.\n",
    "# title(): 转化为大写，例子：\n",
    "# 'Hello world'.title() # 'Hello World'\n",
    "# print(re.sub(r\"\\s|_|\", \"\", \"He llo_worl\\td\"))\n",
    "s = re.sub(r\"(\\s|_|-)+\", \" \", 'some_database_field_name').title().replace(\" \", \"\")  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'someDatabaseFieldName'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = s[0].lower()+s[1:]\n",
    "s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['studentId', 'studentName', 'studentAdd']\n"
     ]
    }
   ],
   "source": [
    "# 完整代码\n",
    "import re\n",
    "def camel(s):\n",
    "    s = re.sub(r\"(\\s|_|-)+\", \" \", s).title().replace(\" \", \"\")\n",
    "    return s[0].lower() + s[1:]\n",
    "\n",
    "# 批量转化\n",
    "def batch_camel(slist):\n",
    "    return [camel(s) for s in slist]\n",
    "    \n",
    "s = batch_camel(['student_id', 'student\\tname', 'student-add'])\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 对文件的操作\n",
    "\n",
    "主要使用标准库os模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "./data/py/test\n",
      ".py\n"
     ]
    }
   ],
   "source": [
    "# 获取文件名的后缀\n",
    "import os\n",
    "file_ext = os.path.splitext('./data/py/test.py')\n",
    "front, ext = file_ext\n",
    "print(front)\n",
    "print(ext)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 读文件的操作函数\n",
    "\n",
    "import os\n",
    "\n",
    "# 创建文件夹\n",
    "def mkdir(path):\n",
    "    isexists = os.path.exists(path)\n",
    "    if not isexists:\n",
    "        os.mkdir(path)\n",
    "\n",
    "# 读取文件信息\n",
    "def openfile(filename):\n",
    "    f = open(filename)\n",
    "    fllist = f.read()\n",
    "    f.close()\n",
    "    return fllist    # 返回读取内容"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<function TextIOWrapper.close()>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 写文件\n",
    "\n",
    "f = open(r\"work/python.txt\", \"w\", encoding=\"utf-8\")\n",
    "print(f.write(\"测试文件写入\"))\n",
    "f.close"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<function TextIOWrapper.close()>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# a写入，文件存在，则在文件内容后追加写入，不存在则创建\n",
    "f = open(r\"work/python.txt\", \"a\", encoding=\"utf-8\")\n",
    "print(f.write(\"测试文件写入\"))\n",
    "f.close"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# with关键字系统会自动关闭文件和处理异常\n",
    "with open(r\"work/python.txt\", \"w\") as f:\n",
    "    f.write(\"hello world!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "work\n",
      "python.txt\n"
     ]
    }
   ],
   "source": [
    "# 获取路径和文件名\n",
    "\n",
    "import os\n",
    "file_ext = os.path.split('work/python.txt')\n",
    "path, filename = file_ext\n",
    "print(path)\n",
    "print(filename)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 批量修改文件后缀\n",
    "\n",
    "import argparse\n",
    "import os\n",
    "\n",
    "# 定义参数\n",
    "def get_parser():\n",
    "    parser = argparse.ArgumentParser(\n",
    "        description='工作目录中文件后缀名修改')\n",
    "    parser.add_argument('work_dir', metavar='WORK_DIR', type=str, nargs=1,\n",
    "                        help='修改后缀名的文件目录')\n",
    "    parser.add_argument('old_ext', metavar='OLD_EXT',\n",
    "                        type=str, nargs=1, help='原来的后缀')\n",
    "    parser.add_argument('new_ext', metavar='NEW_EXT',\n",
    "                        type=str, nargs=1, help='新的后缀')\n",
    "    return parser\n",
    "    \n",
    "# 后缀名的批量修改\n",
    "def batch_rename(work_dir, old_ext, new_ext):\n",
    "    \"\"\"\n",
    "    传递当前目录，原来后缀名，新的后缀名后，批量重命名后缀\n",
    "    \"\"\"\n",
    "    for filename in os.listdir(work_dir):\n",
    "        # 获取得到文件后缀\n",
    "        split_file = os.path.splitext(filename)\n",
    "        file_ext = split_file[1]\n",
    "        # 定位后缀名为old_ext 的文件\n",
    "        if old_ext == file_ext:\n",
    "            # 修改后文件的完整名称\n",
    "            newfile = split_file[0] + new_ext\n",
    "            # 实现重命名操作\n",
    "            os.rename(\n",
    "                os.path.join(work_dir, filename),\n",
    "                os.path.join(work_dir, newfile)\n",
    "            )\n",
    "    print(\"完成重命名\")\n",
    "    print(os.listdir(work_dir))\n",
    "    \n",
    "def main():\n",
    "    \"\"\"\n",
    "    main函数\n",
    "    \"\"\"\n",
    "    # 命令行参数\n",
    "    parser = get_parser()\n",
    "    args = vars(parser.parse_args())\n",
    "    # 从命令行参数中依次解析出参数\n",
    "    work_dir = args['work_dir'][0]\n",
    "    old_ext = args['old_ext'][0]\n",
    "    if old_ext[0] != '.':\n",
    "        old_ext = '.' + old_ext\n",
    "    new_ext = args['new_ext'][0]\n",
    "    if new_ext[0] != '.':\n",
    "        new_ext = '.' + new_ext\n",
    "\n",
    "    batch_rename(work_dir, old_ext, new_ext)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "完成重命名\n",
      "['my_book4.png', 'x1.xlsx', 'a.txt', '轻松入门.png', 'b.txt', 'x2.xlsx', 'python.txt']\n"
     ]
    }
   ],
   "source": [
    "# 将xls批量转换为xlsx\n",
    "\n",
    "def xls_to_xlsx(work_dir):\n",
    "    \"\"\"\n",
    "    传递当前目录，原来后缀名，新的后缀名后，批量重命名后缀\n",
    "    \"\"\"\n",
    "    old_ext, new_ext = '.xls', '.xlsx'\n",
    "    for filename in os.listdir(work_dir):\n",
    "        # 获取得到文件后缀\n",
    "        split_file = os.path.splitext(filename)\n",
    "        file_ext = split_file[1]\n",
    "        # 定位后缀名为old_ext 的文件\n",
    "        if old_ext == file_ext:\n",
    "            # 修改后文件的完整名称\n",
    "            newfile = split_file[0] + new_ext\n",
    "            # 实现重命名操作\n",
    "            os.rename(\n",
    "                os.path.join(work_dir, filename),\n",
    "                os.path.join(work_dir, newfile)\n",
    "            )\n",
    "    print(\"完成重命名\")\n",
    "    print(os.listdir(work_dir))\n",
    "\n",
    "\n",
    "xls_to_xlsx('work')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "文件名：work/a.txt\n",
      "文件名：work/b.txt\n",
      "[1, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "# 比较两个文件在哪些行内容不同，返回这些行的编号，行号编号从1开始。\n",
    "\n",
    "# 统计文件个数\n",
    "def statLineCnt(statfile):\n",
    "    print('文件名：'+statfile)\n",
    "    cnt = 0\n",
    "    with open(statfile, encoding='utf-8') as f:\n",
    "        while f.readline():\n",
    "            cnt += 1\n",
    "        return cnt\n",
    "        \n",
    "#文件之间不同之处的函数\n",
    "def diff(more, cnt, less):\n",
    "    difflist = []\n",
    "    with open(less, encoding='utf-8') as l:\n",
    "        with open(more, encoding='utf-8') as m:\n",
    "            lines = l.readlines()\n",
    "            for i, line in enumerate(lines):\n",
    "                if line.strip() != m.readline().strip():\n",
    "                    difflist.append(i)\n",
    "    if cnt - i > 1:\n",
    "        difflist.extend(range(i + 1, cnt))\n",
    "    return [no+1 for no in difflist]\n",
    "\n",
    "        \n",
    "# 返回的结果行号从1开始\n",
    "# list表示fileA和fileB不同的行的编号\n",
    "\n",
    "def file_diff_line_nos(fileA, fileB):\n",
    "    #try:\n",
    "    cntA = statLineCnt(fileA)\n",
    "    cntB = statLineCnt(fileB)\n",
    "    if cntA > cntB:\n",
    "        return diff(fileA, cntA, fileB)\n",
    "    return diff(fileB, cntB, fileA)\n",
    "\n",
    "    # except Exception as e:\n",
    "    #     print(e)\n",
    "        \n",
    "\n",
    "diff = file_diff_line_nos('work/a.txt', 'work/b.txt')\n",
    "print(diff) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world!!!!!!!!!!!!!!\n",
      "\n",
      "Nice to meet you\n",
      "\n",
      "yes\n",
      "\n",
      "laoqi\n",
      "\n",
      "python\n"
     ]
    }
   ],
   "source": [
    "fa = open(\"work/a.txt\")\n",
    "print(fa.read())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world!!!!\n",
      "\n",
      "Nice to meet you\n",
      "\n",
      "yes\n",
      "\n",
      "learn python with laoqi\n",
      "\n"
     ]
    }
   ],
   "source": [
    "fb = open(\"work/b.txt\")\n",
    "print(fb.read())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "关于文件比较的，实际上，在Python中有对应模块difflib , 提供更多其他格式的文件更详细的比较，大家可参考：\n",
    "https://docs.python.org/3/library/difflib.html?highlight=difflib#module-difflib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "my_book4.png\n",
      "x1.xlsx\n",
      "a.txt\n",
      "轻松入门.png\n",
      "b.txt\n",
      "x2.xlsx\n",
      "python.txt\n",
      "['my_book4.png', '轻松入门.png']\n"
     ]
    }
   ],
   "source": [
    "# 返回指定后缀名的文件\n",
    "\n",
    "import os\n",
    "\n",
    "def find_file(work_dir,extension='jpg'):\n",
    "    lst = []\n",
    "    for filename in os.listdir(work_dir):\n",
    "        print(filename)\n",
    "        splits = os.path.splitext(filename)\n",
    "        ext = splits[1]              # 得到扩展名\n",
    "        if ext == '.'+extension:\n",
    "            lst.append(filename)\n",
    "    return lst\n",
    "\n",
    "r = find_file('work','png') \n",
    "print(r)                   # 返回所有目录下的md文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当前时间：2020-03-03 14:39:08\n",
      "work/my_book4.png\n",
      "                    修改时间[2020-03-03 14:29:36]\n",
      "                    距今[  0天 0时 9]\n",
      "work/x1.xlsx\n",
      "                    修改时间[2020-03-03 14:29:36]\n",
      "                    距今[  0天 0时 9]\n",
      "work/a.txt\n",
      "                    修改时间[2020-03-03 14:29:36]\n",
      "                    距今[  0天 0时 9]\n",
      "work/轻松入门.png\n",
      "                    修改时间[2020-03-03 14:29:36]\n",
      "                    距今[  0天 0时 9]\n",
      "work/b.txt\n",
      "                    修改时间[2020-03-03 14:29:36]\n",
      "                    距今[  0天 0时 9]\n",
      "work/x2.xlsx\n",
      "                    修改时间[2020-03-03 14:29:36]\n",
      "                    距今[  0天 0时 9]\n",
      "work/python.txt\n",
      "                    修改时间[2020-03-03 14:38:57]\n",
      "                    距今[  0天 0时 0]\n"
     ]
    }
   ],
   "source": [
    "# 获取目录下文件的修改时间\n",
    "import os\n",
    "from datetime import datetime\n",
    "\n",
    "print(f\"当前时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n",
    "\n",
    "def get_modify_time(indir):\n",
    "    for root, _, files in os.walk(indir):  # 循环D:\\works目录和子目录\n",
    "        for file in files:\n",
    "            absfile = os.path.join(root, file)\n",
    "            modtime = datetime.fromtimestamp(os.path.getmtime(absfile))\n",
    "            now = datetime.now()\n",
    "            difftime = now-modtime\n",
    "            if difftime.days < 20:  # 条件筛选超过指定时间的文件\n",
    "                print(f\"\"\"{absfile}\n",
    "                    修改时间[{modtime.strftime('%Y-%m-%d %H:%M:%S')}]\n",
    "                    距今[{difftime.days:3d}天{difftime.seconds//3600:2d}时{difftime.seconds%3600//60:2d}]\"\"\"\n",
    "                      )  # 打印相关信息\n",
    "\n",
    "\n",
    "get_modify_time('work')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'work.zip'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 批量压缩文件\n",
    "\n",
    "import zipfile       # 导入zipfile,这个是用来做压缩和解压的Python模块；\n",
    "import os\n",
    "import time\n",
    "\n",
    "\n",
    "def batch_zip(start_dir):\n",
    "    start_dir = start_dir                    # 要压缩的文件夹路径\n",
    "    file_news = start_dir + '.zip'           # 压缩后文件夹的名字\n",
    "\n",
    "    z = zipfile.ZipFile(file_news, 'w', zipfile.ZIP_DEFLATED)\n",
    "    for dir_path, dir_names, file_names in os.walk(start_dir):\n",
    "        # 如果不replace，就从根目录开始复制\n",
    "        f_path = dir_path.replace(start_dir, '')\n",
    "        f_path = f_path and f_path + os.sep          # 实现当前文件夹以及包含的所有文件的压缩\n",
    "        for filename in file_names:\n",
    "            z.write(os.path.join(dir_path, filename), f_path + filename)\n",
    "    z.close()\n",
    "    return file_news\n",
    "\n",
    "\n",
    "batch_zip('work')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "c4ca4238a0b923820dcc509a6f75849b\n",
      "5d41402abc4b2a76b9719d911017c592\n"
     ]
    }
   ],
   "source": [
    "# 对字符串s实现32位加密\n",
    "\n",
    "import hashlib\n",
    "\n",
    "def hash_cry32(s):\n",
    "    m = hashlib.md5()\n",
    "    m.update((str(s).encode('utf-8')))\n",
    "    return m.hexdigest()\n",
    "\n",
    "print(hash_cry32(1))  \n",
    "print(hash_cry32('hello'))  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 日期和时间\n",
    "\n",
    "主要模块：calendar, date, datetime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                  2021\n",
      "\n",
      "      January                   February                   March\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "             1  2  3       1  2  3  4  5  6  7       1  2  3  4  5  6  7\n",
      " 4  5  6  7  8  9 10       8  9 10 11 12 13 14       8  9 10 11 12 13 14\n",
      "11 12 13 14 15 16 17      15 16 17 18 19 20 21      15 16 17 18 19 20 21\n",
      "18 19 20 21 22 23 24      22 23 24 25 26 27 28      22 23 24 25 26 27 28\n",
      "25 26 27 28 29 30 31                                29 30 31\n",
      "\n",
      "       April                      May                       June\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "          1  2  3  4                      1  2          1  2  3  4  5  6\n",
      " 5  6  7  8  9 10 11       3  4  5  6  7  8  9       7  8  9 10 11 12 13\n",
      "12 13 14 15 16 17 18      10 11 12 13 14 15 16      14 15 16 17 18 19 20\n",
      "19 20 21 22 23 24 25      17 18 19 20 21 22 23      21 22 23 24 25 26 27\n",
      "26 27 28 29 30            24 25 26 27 28 29 30      28 29 30\n",
      "                          31\n",
      "\n",
      "        July                     August                  September\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "          1  2  3  4                         1             1  2  3  4  5\n",
      " 5  6  7  8  9 10 11       2  3  4  5  6  7  8       6  7  8  9 10 11 12\n",
      "12 13 14 15 16 17 18       9 10 11 12 13 14 15      13 14 15 16 17 18 19\n",
      "19 20 21 22 23 24 25      16 17 18 19 20 21 22      20 21 22 23 24 25 26\n",
      "26 27 28 29 30 31         23 24 25 26 27 28 29      27 28 29 30\n",
      "                          30 31\n",
      "\n",
      "      October                   November                  December\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "             1  2  3       1  2  3  4  5  6  7             1  2  3  4  5\n",
      " 4  5  6  7  8  9 10       8  9 10 11 12 13 14       6  7  8  9 10 11 12\n",
      "11 12 13 14 15 16 17      15 16 17 18 19 20 21      13 14 15 16 17 18 19\n",
      "18 19 20 21 22 23 24      22 23 24 25 26 27 28      20 21 22 23 24 25 26\n",
      "25 26 27 28 29 30 31      29 30                     27 28 29 30 31\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#csb_print_codes\r\n",
    "import calendar\r\n",
    "my_2021date = calendar.calendar(2021)\r\n",
    "print(my_2021date)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                  2020\n",
      "\n",
      "      January                   February                   March\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "       1  2  3  4  5                      1  2                         1\n",
      " 6  7  8  9 10 11 12       3  4  5  6  7  8  9       2  3  4  5  6  7  8\n",
      "13 14 15 16 17 18 19      10 11 12 13 14 15 16       9 10 11 12 13 14 15\n",
      "20 21 22 23 24 25 26      17 18 19 20 21 22 23      16 17 18 19 20 21 22\n",
      "27 28 29 30 31            24 25 26 27 28 29         23 24 25 26 27 28 29\n",
      "                                                    30 31\n",
      "\n",
      "       April                      May                       June\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "       1  2  3  4  5                   1  2  3       1  2  3  4  5  6  7\n",
      " 6  7  8  9 10 11 12       4  5  6  7  8  9 10       8  9 10 11 12 13 14\n",
      "13 14 15 16 17 18 19      11 12 13 14 15 16 17      15 16 17 18 19 20 21\n",
      "20 21 22 23 24 25 26      18 19 20 21 22 23 24      22 23 24 25 26 27 28\n",
      "27 28 29 30               25 26 27 28 29 30 31      29 30\n",
      "\n",
      "        July                     August                  September\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "       1  2  3  4  5                      1  2          1  2  3  4  5  6\n",
      " 6  7  8  9 10 11 12       3  4  5  6  7  8  9       7  8  9 10 11 12 13\n",
      "13 14 15 16 17 18 19      10 11 12 13 14 15 16      14 15 16 17 18 19 20\n",
      "20 21 22 23 24 25 26      17 18 19 20 21 22 23      21 22 23 24 25 26 27\n",
      "27 28 29 30 31            24 25 26 27 28 29 30      28 29 30\n",
      "                          31\n",
      "\n",
      "      October                   November                  December\n",
      "Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su\n",
      "          1  2  3  4                         1          1  2  3  4  5  6\n",
      " 5  6  7  8  9 10 11       2  3  4  5  6  7  8       7  8  9 10 11 12 13\n",
      "12 13 14 15 16 17 18       9 10 11 12 13 14 15      14 15 16 17 18 19 20\n",
      "19 20 21 22 23 24 25      16 17 18 19 20 21 22      21 22 23 24 25 26 27\n",
      "26 27 28 29 30 31         23 24 25 26 27 28 29      28 29 30 31\n",
      "                          30\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import calendar\n",
    "\n",
    "mydate = calendar.calendar(2020)\n",
    "print(mydate)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 判断某一年是否为闰年\n",
    "import calendar\n",
    "year = 2020\n",
    "calendar.isleap(year)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    January 2020\n",
      "Mo Tu We Th Fr Sa Su\n",
      "       1  2  3  4  5\n",
      " 6  7  8  9 10 11 12\n",
      "13 14 15 16 17 18 19\n",
      "20 21 22 23 24 25 26\n",
      "27 28 29 30 31\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import calendar\n",
    "month_calendar = calendar.month(2020, 1)\n",
    "print(month_calendar)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(4, 31)\n"
     ]
    }
   ],
   "source": [
    "print(calendar.monthrange(2021,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020年1月第一天是那一周的第2天.\n",
      "2020年1月共计31天。\n"
     ]
    }
   ],
   "source": [
    "# 某月的天数\n",
    "weekday, days = calendar.monthrange(2020, 1)\n",
    "print(f\"2020年1月第一天是那一周的第{weekday}天.\")\n",
    "print(f\"2020年1月共计{days}天。\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当月第一天:2020-02-01\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 某个月的第一天\n",
    "from datetime import date\n",
    "month_first_day = date(2020, 2, 1)\n",
    "print(f\"当月第一天:{month_first_day}\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当月最后一天:2020-01-31\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 某月的最后一天\n",
    "_, days = calendar.monthrange(2020, 1)\n",
    "month_last_day = date(2020, 1, days)\n",
    "print(f\"当月最后一天:{month_last_day}\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-03-03\n",
      "2020-03-03 14:39:30.457334\n",
      "2020-03-03 14:39:30\n"
     ]
    }
   ],
   "source": [
    "# 当前日期和时间\n",
    "\n",
    "from datetime import date, datetime\n",
    "import time\n",
    "\n",
    "today_date = date.today()\n",
    "print(today_date)  \n",
    "\n",
    "today_time = datetime.today()\n",
    "print(today_time)  \n",
    "\n",
    "local_time = time.localtime()\n",
    "print(time.strftime(\"%Y-%m-%d %H:%M:%S\", local_time)) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "time.struct_time(tm_year=2019, tm_mon=12, tm_mday=22, tm_hour=10, tm_min=10, tm_sec=8, tm_wday=6, tm_yday=356, tm_isdst=-1)\n"
     ]
    }
   ],
   "source": [
    "# 字符串转化为时间格式\n",
    "\n",
    "struct_time = time.strptime('2019-12-22 10:10:08', \"%Y-%m-%d %H:%M:%S\")\n",
    "print(struct_time)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "time.struct_time(tm_year=2020, tm_mon=3, tm_mday=3, tm_hour=14, tm_min=40, tm_sec=18, tm_wday=1, tm_yday=63, tm_isdst=0)\n",
      "03-03-2020 14:40:18\n"
     ]
    }
   ],
   "source": [
    "# 时间转化为字符串格式\n",
    "\n",
    "from time import strftime, strptime, localtime\n",
    "\n",
    "print(localtime())\n",
    "\n",
    "print(strftime(\"%m-%d-%Y %H:%M:%S\", localtime())) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 迭代器 生成器 装饰器\n",
    "\n",
    "主要使用itertools模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n",
      "-1\n"
     ]
    }
   ],
   "source": [
    "# 寻找第n次出现的位置\n",
    "\n",
    "def search_n(s, c, n):\n",
    "    size = 0\n",
    "    for i, x in enumerate(s):\n",
    "        if x == c:\n",
    "            size += 1\n",
    "        if size == n:\n",
    "            return i\n",
    "    return -1\n",
    "\n",
    "print(search_n(\"fdasadfadf\", \"a\", 3))\n",
    "print(search_n(\"fdasadfadf\", \"a\", 30))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 1, 2, 3, 5]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 斐波那契数列生成器函数\n",
    "\n",
    "def fibonacci(n):\n",
    "    a, b = 1, 1\n",
    "    for _ in range(n):\n",
    "        yield a\n",
    "        a, b = b, a + b\n",
    "\n",
    "list(fibonacci(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 找出所有重复元素\n",
    "\n",
    "from collections import Counter\n",
    "\n",
    "def find_all_duplicates(lst):\n",
    "    c = Counter(lst)\n",
    "    return list(filter(lambda k: c[k] > 1, c))\n",
    "\n",
    "find_all_duplicates([1, 2, 2, 3, 3, 3]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Counter({'apple': 1, 'orange': 3, 'computer': 2})"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如下两个列表，统计两个列表中每个单词出现的次数\n",
    "\n",
    "from collections import Counter\n",
    "a = ['apple', 'orange', 'computer', 'orange']\n",
    "b = ['computer', 'orange']\n",
    "\n",
    "ca = Counter(a)\n",
    "cb = Counter(b)\n",
    "#Counter对象间可以做数学运算\n",
    "ca + cb  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Counter({'apple': 1, 'orange': 3, 'computer': 3, 'abc': 1, 'face': 1})"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 多个列表内元素个数的统计\n",
    "\n",
    "def sumc(*c):\n",
    "    if (len(c) < 1):\n",
    "        return\n",
    "    mapc = map(Counter, c)\n",
    "    s = Counter([])\n",
    "    for ic in mapc: # ic 是一个Counter对象\n",
    "        s += ic\n",
    "    return s\n",
    "    \n",
    "sumc(a, b, ['abc'], ['face', 'computer'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cloud\n",
      "{'date': '2019-12-15', 'weather': 'cloud'}\n",
      "{'date': '2019-12-14', 'weather': 'cloud'}\n",
      "sunny\n",
      "{'date': '2019-12-13', 'weather': 'sunny'}\n"
     ]
    }
   ],
   "source": [
    "# 对如下数据，按照weather的值进行分组\n",
    "\n",
    "a = [{'date': '2019-12-15', 'weather': 'cloud'}, {'date': '2019-12-13', 'weather': 'sunny'}, {'date': '2019-12-14', 'weather': 'cloud'}]\n",
    "\n",
    "from itertools import groupby\n",
    "a.sort(key=lambda x: x['weather'])\n",
    "for k, items in  groupby(a,key=lambda x:x['weather']):\n",
    "     print(k)\n",
    "     for i in items:\n",
    "         print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cloud\n",
      "{'date': '2019-12-15', 'weather': 'cloud'}\n",
      "{'date': '2019-12-14', 'weather': 'cloud'}\n",
      "sunny\n",
      "{'date': '2019-12-13', 'weather': 'sunny'}\n"
     ]
    }
   ],
   "source": [
    "# 对上述问题的另外一种实现\n",
    "\n",
    "from operator import itemgetter\n",
    "from itertools import groupby\n",
    "\n",
    "a.sort(key=itemgetter('weather'))\n",
    "for k, items in groupby(a, key=itemgetter('weather')):\n",
    "     print(k)\n",
    "     for i in items:\n",
    "         print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cloud\n",
      "{'date': '2019-12-14', 'weather': 'cloud'}\n",
      "{'date': '2019-12-15', 'weather': 'cloud'}\n",
      "sunny\n",
      "{'date': '2019-12-13', 'weather': 'sunny'}\n"
     ]
    }
   ],
   "source": [
    "# itemgetter是一个类，itemgetter('weather')返回一个可调用的对象，它的参数可有多个\n",
    "a.sort(key=itemgetter('weather', 'date'))\n",
    "for k, items in groupby(a, key=itemgetter('weather')):\n",
    "     print(k)\n",
    "     for i in items:\n",
    "         print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x7fd6dd533cd0>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 生成器表达式\n",
    "lst = [1,2,3]\n",
    "(i**i for i in lst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1, 2, 3, 4, 5]]\n",
      "[[1, 2, 3], [4, 5]]\n"
     ]
    }
   ],
   "source": [
    "# list分组(生成器版)\n",
    "from math import ceil\n",
    "\n",
    "def divide_iter(lst, n):\n",
    "    if n <= 0:\n",
    "        yield lst\n",
    "        return\n",
    "    i, div = 0, ceil(len(lst) / n)\n",
    "    while i < n:\n",
    "        yield lst[i * div: (i + 1) * div]\n",
    "        i += 1\n",
    "\n",
    "one = list(divide_iter([1, 2, 3, 4, 5], 0))  \n",
    "two = list(divide_iter([1, 2, 3, 4, 5], 2))\n",
    "\n",
    "print(one)\n",
    "print(two)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5, 6, 7, 8, 'python', 6, 9]\n"
     ]
    }
   ],
   "source": [
    "#多层列表展开成单层列表\n",
    "a=[1,2,[3,4,[5,6],7],8,[\"python\",6],9]\n",
    "def function(lst):\n",
    "    for i in lst:\n",
    "        if type(i)==list:\n",
    "            yield from function(i)\n",
    "        else:\n",
    "            yield i\n",
    "print(list(function(a)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "test list append time: 0.008999347686767578\n",
      "test list comprehension time: 0.004084587097167969\n",
      "append/compre: 2.203\n"
     ]
    }
   ],
   "source": [
    "#测试函数执行时间的装饰器示例\n",
    "import time\n",
    "def timing_func(fn):\n",
    "    def wrapper():\n",
    "        start=time.time()\n",
    "        fn()   #执行传入的fn参数\n",
    "        stop=time.time()\n",
    "        return (stop-start)\n",
    "    return wrapper\n",
    "    \n",
    "@timing_func\n",
    "def test_list_append():\n",
    "    lst=[]\n",
    "    for i in range(0,100000):\n",
    "        lst.append(i)  \n",
    "        \n",
    "@timing_func\n",
    "def test_list_compre():\n",
    "    [i for i in range(0,100000)]  #列表生成式\n",
    "    \n",
    "a=test_list_append()\n",
    "c=test_list_compre()\n",
    "print(\"test list append time:\",a)\n",
    "print(\"test list comprehension time:\",c)\n",
    "print(\"append/compre:\",round(a/c,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "division by zero: 1\n",
      "division by zero: 2\n",
      "division by zero: 3\n",
      "division by zero: 4\n",
      "division by zero: 5\n",
      "division by zero: 6\n",
      "division by zero: 7\n",
      "division by zero: 8\n",
      "division by zero: 9\n",
      "division by zero: 10\n",
      "spending time:1.0\n",
      "list index out of range: 1\n",
      "list index out of range: 2\n",
      "list index out of range: 3\n",
      "list index out of range: 4\n",
      "list index out of range: 5\n",
      "list index out of range: 6\n",
      "list index out of range: 7\n",
      "list index out of range: 8\n",
      "list index out of range: 9\n",
      "list index out of range: 10\n",
      "spending time:1.0\n"
     ]
    }
   ],
   "source": [
    "# 统计某个异常重复出现指定次数时，经历的时长\n",
    "\n",
    "import time\n",
    "import math\n",
    "\n",
    "def excepter(f):\n",
    "    i = 0\n",
    "    t1 = time.time()\n",
    "    def wrapper(): \n",
    "        try:\n",
    "            f()\n",
    "        except Exception as e:\n",
    "            nonlocal i\n",
    "            i += 1\n",
    "            print(f'{e.args[0]}: {i}')\n",
    "            t2 = time.time()\n",
    "            if i == n:\n",
    "                print(f'spending time:{round(t2-t1,2)}')\n",
    "    return wrapper\n",
    "    \n",
    "n = 10 # except count\n",
    "\n",
    "@excepter\n",
    "def divide_zero_except():\n",
    "    time.sleep(0.1)\n",
    "    j = 1/(40-20*2)\n",
    "\n",
    "# test zero divived except\n",
    "for _ in range(n):\n",
    "    divide_zero_except()\n",
    "\n",
    "\n",
    "@excepter\n",
    "def outof_range_except():\n",
    "    a = [1,3,5]\n",
    "    time.sleep(0.1)\n",
    "    print(a[3])\n",
    "    \n",
    "# test out of range except\n",
    "for _ in range(n):\n",
    "    outof_range_except()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]\n"
     ]
    }
   ],
   "source": [
    "#编写一个迭代器，通过循环语句，实现对某个正整数的依次递减1，直到0.\n",
    "class Descend(Iterator):\n",
    "    def __init__(self,N):\n",
    "        self.N=N\n",
    "        self.a=0\n",
    "    def __iter__(self):\n",
    "        return self \n",
    "    def __next__(self):\n",
    "        while self.a<self.N:\n",
    "            self.N-=1\n",
    "            return self.N\n",
    "        raise StopIteration\n",
    "    \n",
    "descend_iter=Descend(10)\n",
    "print(list(descend_iter))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 典型项目"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_133/2415558783.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     29\u001b[0m     \u001b[0msmt_p\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mquit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     30\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 31\u001b[0;31m \u001b[0msender_mail\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/tmp/ipykernel_133/2415558783.py\u001b[0m in \u001b[0;36msender_mail\u001b[0;34m()\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0msender_mail\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      8\u001b[0m     \u001b[0msmt_p\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msmtplib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSMTP\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m     \u001b[0msmt_p\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhost\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'smtp.qq.com'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mport\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m25\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     10\u001b[0m     \u001b[0msender\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpassword\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'youremail@qq.com'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"**************\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0msmt_p\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlogin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msender\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpassword\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/envs/python35-paddle120-env/lib/python3.7/smtplib.py\u001b[0m in \u001b[0;36mconnect\u001b[0;34m(self, host, port, source_address)\u001b[0m\n\u001b[1;32m    334\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdebuglevel\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    335\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_print_debug\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'connect:'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mhost\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mport\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 336\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msock\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_socket\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhost\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mport\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    337\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfile\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    338\u001b[0m         \u001b[0;34m(\u001b[0m\u001b[0mcode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetreply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/envs/python35-paddle120-env/lib/python3.7/smtplib.py\u001b[0m in \u001b[0;36m_get_socket\u001b[0;34m(self, host, port, timeout)\u001b[0m\n\u001b[1;32m    305\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_print_debug\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'connect: to'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mhost\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mport\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msource_address\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    306\u001b[0m         return socket.create_connection((host, port), timeout,\n\u001b[0;32m--> 307\u001b[0;31m                                         self.source_address)\n\u001b[0m\u001b[1;32m    308\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    309\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhost\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'localhost'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mport\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msource_address\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/envs/python35-paddle120-env/lib/python3.7/socket.py\u001b[0m in \u001b[0;36mcreate_connection\u001b[0;34m(address, timeout, source_address)\u001b[0m\n\u001b[1;32m    714\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0msource_address\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    715\u001b[0m                 \u001b[0msock\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msource_address\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 716\u001b[0;31m             \u001b[0msock\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msa\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    717\u001b[0m             \u001b[0;31m# Break explicitly a reference cycle\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    718\u001b[0m             \u001b[0merr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "# 自动拳法邮件\n",
    "import smtplib\n",
    "from email import (header)\n",
    "from email.mime import (text, application, multipart)\n",
    "import time\n",
    "\n",
    "def sender_mail():\n",
    "    smt_p = smtplib.SMTP()\n",
    "    smt_p.connect(host='smtp.qq.com', port=25)\n",
    "    sender, password = 'youremail@qq.com', \"**************\"\n",
    "    smt_p.login(sender, password)\n",
    "    receiver_addresses, count_num = [\n",
    "        'email@163.com', 'email@163.com'], 1\n",
    "    for email_address in receiver_addresses:\n",
    "        try:\n",
    "            msg = multipart.MIMEMultipart()\n",
    "            msg['From'] = \"zhenguo\"\n",
    "            msg['To'] = email_address\n",
    "            msg['subject'] = header.Header('这是邮件主题通知', 'utf-8')\n",
    "            msg.attach(text.MIMEText(\n",
    "                '这是一封测试邮件，请勿回复本邮件~', 'plain', 'utf-8'))\n",
    "            smt_p.sendmail(sender, email_address, msg.as_string())\n",
    "            time.sleep(10)\n",
    "            print('第%d次发送给%s' % (count_num, email_address))\n",
    "            count_num = count_num + 1\n",
    "        except Exception as e:\n",
    "            print('第%d次给%s发送邮件异常' % (count_num, email_address))\n",
    "            continue\n",
    "    smt_p.quit()\n",
    "\n",
    "sender_mail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 二分搜索\n",
    "\n",
    "def binarySearch(arr, left, right, x):\n",
    "    while left <= right:\n",
    "\n",
    "        mid = int(left + (right - left) / 2); # 找到中间位置。求中点写成(left+right)/2更容易溢出，所以不建议这样写\n",
    "\n",
    "        # 检查x是否出现在位置mid\n",
    "        if arr[mid] == x:\n",
    "            print('found %d 在索引位置%d 处' %(x,mid))\n",
    "            return mid\n",
    "\n",
    "            # 假如x更大，则不可能出现在左半部分\n",
    "        elif arr[mid] < x:\n",
    "            left = mid + 1 #搜索区间变为[mid+1,right]\n",
    "            print('区间缩小为[%d,%d]' %(mid+1,right))\n",
    "\n",
    "        # 同理，假如x更小，则不可能出现在右半部分\n",
    "        elif x<arr[mid]:\n",
    "            right = mid - 1 #搜索区间变为[left,mid-1]\n",
    "            print('区间缩小为[%d,%d]' %(left,mid-1))\n",
    "\n",
    "    # 假如搜索到这里，表明x未出现在[left,right]中\n",
    "    return -1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "区间缩小为[0,2]\n",
      "found 5 在索引位置1 处\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binarySearch([4,5,6,7,10,20,100],0,6,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "区间缩小为[0,2]\n",
      "区间缩小为[0,0]\n",
      "found 4 在索引位置0 处\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binarySearch([4,5,6,7,10,20,100],0,6,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mkdir: cannot create directory ‘/home/aistudio/external-libraries’: File exists\n",
      "Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple/\n",
      "Collecting lxml\n",
      "\u001b[?25l  Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/85/9e/93e2c3af278c7c8b6826666bbcb145af2829bd761c3b329e51cd6343836c/lxml-4.5.0-cp37-cp37m-manylinux1_x86_64.whl (5.7MB)\n",
      "\u001b[K     |████████████████████████████████| 5.7MB 47.9MB/s eta 0:00:01\n",
      "\u001b[?25hInstalling collected packages: lxml\n",
      "Successfully installed lxml-4.5.0\n",
      "\u001b[33mWARNING: Target directory /home/aistudio/external-libraries/lxml already exists. Specify --upgrade to force replacement.\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!mkdir /home/aistudio/external-libraries\n",
    "!pip install lxml -t /home/aistudio/external-libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import sys\n",
    "sys.path.append('/home/aistudio/external-libraries')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 爬取天气数据并解析温度值\n",
    "import requests\n",
    "from lxml import etree\n",
    "import pandas as pd\n",
    "import re\n",
    "\n",
    "url = 'http://www.weather.com.cn/weather1d/101010100.shtml#input'\n",
    "with requests.get(url) as res:\n",
    "    content = res.content\n",
    "    html = etree.HTML(content)\n",
    "    \n",
    "location = html.xpath('//*[@id=\"around\"]//a[@target=\"_blank\"]/span/text()')\n",
    "temperature = html.xpath('//*[@id=\"around\"]/div/ul/li/a/i/text()')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "温度列\n",
      "0     10/-2°C\n",
      "1     11/-3°C\n",
      "2      9/-6°C\n",
      "3     10/-5°C\n",
      "4      9/-1°C\n",
      "5     10/-2°C\n",
      "6      8/-7°C\n",
      "7      12/0°C\n",
      "8      3/-8°C\n",
      "9     1/-11°C\n",
      "10    12/-5°C\n",
      "11     9/-3°C\n",
      "12     8/-3°C\n",
      "13     8/-3°C\n",
      "14     8/-3°C\n",
      "15     8/-3°C\n",
      "16     9/-3°C\n",
      "17     8/-2°C\n",
      "18     8/-3°C\n",
      "19     8/-3°C\n",
      "20     8/-2°C\n",
      "21     8/-2°C\n",
      "22     8/-2°C\n",
      "23     8/-3°C\n",
      "Name: temperature, dtype: object\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame({'location':location, 'temperature':temperature})\n",
    "print('温度列')\n",
    "print(df['temperature'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    location temperature  high  low\n",
      "0         香河     10/-2°C    10   -2\n",
      "1         涿州     11/-3°C    11   -3\n",
      "2         唐山      9/-6°C     9   -6\n",
      "3         沧州     10/-5°C    10   -5\n",
      "4         天津      9/-1°C     9   -1\n",
      "5         廊坊     10/-2°C    10   -2\n",
      "6         太原      8/-7°C     8   -7\n",
      "7        石家庄      12/0°C    12    0\n",
      "8         涿鹿      3/-8°C     3   -8\n",
      "9        张家口     1/-11°C     1  -11\n",
      "10        保定     12/-5°C    12   -5\n",
      "11        三河      9/-3°C     9   -3\n",
      "12      北京孔庙      8/-3°C     8   -3\n",
      "13     北京国子监      8/-3°C     8   -3\n",
      "14   中国地质博物馆      8/-3°C     8   -3\n",
      "15      月坛公园      8/-3°C     8   -3\n",
      "16   明城墙遗址公园      9/-3°C     9   -3\n",
      "17  北京市规划展览馆      8/-2°C     8   -2\n",
      "18       什刹海      8/-3°C     8   -3\n",
      "19      南锣鼓巷      8/-3°C     8   -3\n",
      "20      天坛公园      8/-2°C     8   -2\n",
      "21      北海公园      8/-2°C     8   -2\n",
      "22      景山公园      8/-2°C     8   -2\n",
      "23     北京海洋馆      8/-3°C     8   -3\n"
     ]
    }
   ],
   "source": [
    "df['high'] = df['temperature'].apply(lambda x: int(re.match('(-?[0-9]*?)/-?[0-9]*?°C', x).group(1) ) )\n",
    "df['low'] = df['temperature'].apply(lambda x: int(re.match('-?[0-9]*?/(-?[0-9]*?)°C', x).group(1) ) )\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5050"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 用一行代码计算1~100的整数的和\n",
    "sum(range(1, 101))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n"
     ]
    }
   ],
   "source": [
    "# 如何在一个函数内部修改全局变量\n",
    "\n",
    "a = 5\n",
    "def foo():\n",
    "    global a\n",
    "    a = 100\n",
    "\n",
    "foo()\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 解释Python中的GIL\n",
    "\n",
    "回答：GIL全称Global Interpreter Lock。\n",
    "\n",
    " GIL 是python的全局解释器锁，同一进程中假如有多个线程运行，一个线程在运行python程序的时候会霸占python解释器（加了一把锁即GIL），使该进程内的其他线程无法运行，等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作，则解释器锁解开，使其他线程运行。所以在多线程中，线程的运行仍是有先后顺序的，并不是同时进行。\n",
    "\n",
    "多进程中因为每个进程都能被系统分配资源，相当于每个进程有了一个python解释器，所以多进程可以实现多个进程的同时运行，缺点是进程系统资源开销大\n",
    "\n",
    "\n",
    "注：关于线程的问题，可以参考微信公众号：老齐教室，内有专门的文章进行讲解。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 简述面向对象中__new__和__init__区别\n",
    "\n",
    "1、`__new__`至少要有一个参数cls，代表当前类，此参数在实例化时由Python解释器自动识别\n",
    "\n",
    "2、`__new__`必须要有返回值，返回实例化出来的实例，这点在自己实现`__new__`时要特别注意，可以return父类（通过super(当前类名, cls)）`__new__`出来的实例，或者直接是object的`__new__`出来的实例\n",
    "\n",
    "3、`__init__`有一个参数self，就是这个`__new__`返回的实例，`__init__`在`__new__`的基础上可以完成一些其它初始化的动作，`__init__`不需要返回值\n",
    "\n",
    "4、如果`__new__`创建的是当前类的实例，会自动调用`__init__`函数，通过return语句里面调用的`__new__`函数的第一个参数是cls来保证是当前类实例，如果是其他类的类名，；那么实际创建返回的就是其他类的实例，其实就不会调用当前类的`__init__`函数，也不会调用其他类的`__init__`函数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[16, 25]\n"
     ]
    }
   ],
   "source": [
    "# 已知列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25]，并使用列表推导式提取出大于10的数，最终输出[16,25]\n",
    "\n",
    "lst = [1,2,3,4,5]\n",
    "\n",
    "def pw2(x): return x*x\n",
    "\n",
    "r = map(pw2, lst)\n",
    "\n",
    "print([i for i in r if i>10])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 避免转义给字符串加哪个字母表示原始字符串？\n",
    "\n",
    "\n",
    "r , 表示需要原始字符串，不转义特殊字符，例如：r'\\nhello'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\\\nhello'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r'\\nhello'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['老齐教室']\n"
     ]
    }
   ],
   "source": [
    "# <div class=\"nam\">老齐教室</div>，用正则匹配出标签里面的内容（“老齐教室”），其中class的类名是不确定的\n",
    "\n",
    "import re\n",
    "s = '<div class=\"nam\">老齐教室</div>'\n",
    "res = re.findall(r'<div class=\".*\">(.*?)</div>', s)\n",
    "print(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "right. continue\n"
     ]
    },
    {
     "ename": "AssertionError",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAssertionError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-196-f8063c20230e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'right. continue'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      8\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0;32massert\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m<\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     10\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'False'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mAssertionError\u001b[0m: "
     ]
    }
   ],
   "source": [
    "# 举例说明，在Python中如何实现断言\n",
    "\n",
    "# 回答：使用assert()实现断言\n",
    "\n",
    "n = 2\n",
    "assert(n>1)\n",
    "print('right. continue')\n",
    "\n",
    "assert(n<1)\n",
    "print('False')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'age': 28, 'city': 'soochow', 'name': 'laoqi', 'offical accounts': '老齐教室'}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对如下字典d的键进行排序，要求从小打到的顺序。\n",
    "d = {\"name\":\"laoqi\", \"age\":28, \"city\":\"soochow\", \"offical accounts\":\"老齐教室\"}\n",
    "lst = sorted(d.items(), key=lambda i:i[0], reverse=False)\n",
    "dict(lst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a： <class 'tuple'>\n",
      "b： <class 'int'>\n",
      "c： <class 'str'>\n"
     ]
    }
   ],
   "source": [
    "# a=（1）b=(1)，c=(\"1\") 分别是什么类型的数据？\n",
    "a = (1,)\n",
    "b = (1)\n",
    "c = (\"1\") \n",
    "print('a：', type(a))\n",
    "print('b：', type(b))\n",
    "print('c：', type(c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "#设计一个立方体类Box，定义三个属性，分别是长，宽，高。定义二个方法，分别计算并输出立方体的体积和表面积。\n",
    "\n",
    "class box():\n",
    "    def __init__(self,length,width,high):\n",
    "        self.length = length\n",
    "        self.width = width\n",
    "        self.high = high\n",
    "    def volume(self):\n",
    "        print(self.length*self.width*self.high)\n",
    "    def superficial(self):\n",
    "        print(2*(self.length*self.width+self.length*self.high+self.width*self.high))\n",
    "b1 = box(1,1,1)\n",
    "b1.volume()\n",
    "b1.superficial()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "py35-paddle1.2.0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
